Categories
TypeScript

Using TypeScript — Never and Unknown Types, Removing null from Unions

Spread the love

TypeScript is a natural extension of JavaScript that’s used in many projects in place of JavaScript.

However, not everyone knows how it actually works.

In this article, we’ll look at the use of the never type, unknown type, and removing null from a union.

Never Type

TypeScript provides us with the never type for situations where the type guard has dealt with all the possible types for a value.

Once all the possible types have been handled then the compiler will only allow a value to be assigned to the never type.

For instance, if we have a switch statement:

const getTax = (price: number, format: boolean): string | number => {
  if (typeof price !== "number") {
    return 0;
  }

if (format) {
    return (price * 0.2).toFixed(2) as string;
  }
  return (price * 0.2) as number;
};

let tax = getTax(100, false);
switch (typeof tax) {
  case "number":
    console.log(`Number: ${tax.toFixed(2)}`);
    break;
  case "string":
    console.log(tax);
    break;
  default:
    let value: never = tax;
    console.log(`Unexpected type for value: ${value}`);
}

Then we assign the value for the default case to a variable with a never type since we handled the string and number in the previous cases.

Using the unknown Type

The unknown type is a safer alternative to any .

It indicates that we don’t know the type of the value.

We can assign things to an unknown type.

For instance, we can write:

let tax: unknown = getTax(100, false);

tax can’t be assigned to a variable of another type without a type assertion.

Nullable Types

null and undefined types aren’t in the TypeScript type system.

However, we can create nullable versions of variables by using nullable types.

For instance, we can write:

const getTax = (price: number, format: boolean): string | number | null => {
  if (typeof price !== "number") {
    return null;
  }

if (format) {
    return (price * 0.2).toFixed(2) as string;
  }
  return (price * 0.2) as number;
};

Now we can return null in addition to number or string .

For parameter, we can write:

const getTax = (price?: number, format: boolean): string | number | null => {
  if (typeof price !== "number") {
    return null;
  }

  if (format) {
    return (price * 0.2).toFixed(2) as string;
  }
  return (price * 0.2) as number;
};

We put a ? beside the parameter name so that we indicate that it might be null or undefined .

Restricting Nullable Assignments

We can restrict the use of null or undefined by enabling the strictNullChecks compiler setting.

If we set it to true , then we can’t assign null to something that’s not the type of variable that has other data types specified.

If we have that on, then we’ll get ‘Type ‘null’ is not assignable to type ‘string | number’.ts(2322)’.

So we’ve to add null to the type union as we have before.

Removing null from a Union

We can remove null from a union type with a non-null assertion.

For instance, if we write:

let tax: string | number = getTax(100, false)!;

Then we make sure that we don’t have null returned and assigned to tax .

We can also remove null s with type guards.

For instance, we can write:

if (tax !== null) {
  //..
}

to do null checks before proceeding.

Definite Assignment Assertion

If strictNullChecks option is enabled, the compiler will report an error if a variable is used before being assigned a value.

For instance, we can add null to the union type of the tax variable, and then assert it later.

We write:

let tax: string | number | null = getTax(100, false);

Then we can narrow it to the type we want in other statements with as or brackets.

Conclusion

The never type is used when we handled all the other types in our conditional statements.

unknown is a safer alternative to any . Variables of unknown type can’t be assigned to other variables.

There are various ways to remove a type from a union.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *